package com.ruoyi.project.digital.controller.api;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.email.EmailVerificationUtil;
import com.ruoyi.common.sms.MsgResult;
import com.ruoyi.common.sms.ali.AliMsgApi;
import com.ruoyi.common.sms.ali.MsgBizEnum;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.framework.aspectj.lang.annotation.NoNeedAccess;
import com.ruoyi.framework.interceptor.annotation.RepeatSubmit;
import com.ruoyi.framework.redis.RedisCache;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.domain.Result;
import com.ruoyi.project.common.utils.Constant;
import com.ruoyi.project.digital.config.properties.SysUrlProperties;
import com.ruoyi.project.digital.domain.*;
import com.ruoyi.project.digital.domain.dto.CommityDto;
import com.ruoyi.project.digital.domain.dto.LoginDto;
import com.ruoyi.project.digital.domain.dto.LoginWechatUser;
import com.ruoyi.project.digital.domain.dto.RegisterDto;
import com.ruoyi.project.digital.domain.vo.*;
import com.ruoyi.project.digital.service.*;
import com.ruoyi.project.system.service.ISysConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import jodd.util.StringUtil;
import lombok.SneakyThrows;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthQqRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.request.AuthWeChatOpenRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.apache.axis.types.Id;
import org.apache.http.client.HttpClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @program: zxht
 * @Date: 2020/12/16 10:13
 * @Author: syc
 * @Description:
 */
@Api(value = "授权登录", tags = "授权登录")
@RestController
@RequestMapping(value = "api/wu/account")
public class UserLoginApiController extends BaseController {
    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private WxMaService wxMaUserService;
    @Autowired
    private WechatUserLoginService wechatUserLoginService;

    @Autowired
    private SysUrlProperties sysUrlProperties;

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ITUserService itUserService;
    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private IPetService petService;
    @Autowired
    private ITaskService taskService;
    @Autowired
    private ITUserService userService;
    @Autowired
    private IUserTaskService userTaskService;
    @Autowired
    private ISysConfigService configService;
    @Autowired
    private WechatUserTokenService wechatUserTokenService;


    @ApiOperation(value = "获取短信验证码")

    @GetMapping("sms/code")
    @NoNeedAccess
    @RepeatSubmit
    public Result sendRegisterMsg(@NotNull(message = "手机号不能为空") String phone) {
        // 生成验证码
        String code = null;
        if (EnvUtil.isDev()) {
            code = "123456";
        } else {
            code = VerifyCodeUtils.generateNumberCode(6);
        }
        //手机号检测
        if (StringUtils.checkPhoneNumber(phone)) {

            // 判断手机号是否注册过了
            TUser one = itUserService.getUserName(phone);
            if (one != null) {
                return Result.error("该手机号已被注册");
            }
            HashMap<String, String> param = new HashMap<>();
            param.put("code", code);
            MsgResult response = AliMsgApi.sendMsg(phone, MsgBizEnum.REGISTER_USER, param);
            System.out.println("短信验证码响应："+response);
        }
        //邮箱检测
        if (StringUtils.isValidEmail(phone)) {

            // 判断手机号是否注册过了
            TUser one = itUserService.getUserName(phone);
            if (one != null) {
                return Result.error("该邮箱已被注册");
            }
            boolean verificationCode = EmailVerificationUtil.sendVerificationCode(phone, code);
            System.out.println("邮箱验证码发送是否成功："+verificationCode);
        }
        String smsKey = com.ruoyi.common.constant.Constants.REDIS_PRE_SMS + phone;
        // 有效期5分钟
        redisCache.setCacheObject(smsKey, code, 5, TimeUnit.MINUTES);

        return Result.success("发送成功", code);
    }


    @ApiOperation(value = "验证短信验证码是否正确")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "smsCode", value = "短信验证码", paramType = "query", dataType = "string"),
            @ApiImplicitParam(name = "phone", value = "手机号", paramType = "query", dataType = "string")
    })
    @GetMapping("/valid/smsCode")
    @NoNeedAccess
    public Result validSmsCode(@NotEmpty(message = "账号不能为空") String phone, @NotEmpty(message = "短信验证码不能为空") String smsCode) {
        // 校验验证码
        String key = com.ruoyi.common.constant.Constants.REDIS_PRE_SMS + phone;
        String verifyCode = redisCache.getCacheObject(key);
        if (EnvUtil.isDev()) {
            verifyCode = "123456";
        } else {
            verifyCode = redisCache.getCacheObject(key);
        }
        if (StringUtil.isBlank(verifyCode)) {
            // 短信验证码已过期
            return Result.error("验证码错误");
        } else if (!smsCode.equals(verifyCode)) {
            // 短信验证码验证失败
            return Result.error("验证码错误");
        }
        return Result.success("验证成功");

    }

    @ApiOperation(value = "注册接口")
    @GetMapping("/reset/{id}/{password}")
    public Result reset(@PathVariable Long id, @PathVariable String password) {
        // 用户注册
        TUser user = itUserService.selectTUserById(id);
        user.setPassword(SecurityUtils.encryptPassword(password));
        itUserService.updateTUser(user);
        return Result.success();
    }

    @ApiOperation(value = "注册接口")
    @PostMapping("/register")
    public Result register(@RequestBody RegisterDto registerDto) {
        // 用户注册
        Result result = itUserService.register(registerDto);
        // 插入任务
        QueryWrapper<TUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_name",registerDto.getPhone());
        TUser tUser = userService.getOne(queryWrapper);
        QueryWrapper<Task> taskQueryWrapper = new QueryWrapper<>();
        taskQueryWrapper.eq("is_day","1").ne("code", "first");
        List<Task> taskList = taskService.list(taskQueryWrapper);
        if (null != tUser && !taskList.isEmpty()){
            for (Task task : taskList) {
                UserTask userTask = new UserTask();
                userTask.setUserId(tUser.getId());
                userTask.setTaskId(task.getId());
                userTask.setGetTime(DateUtils.getNowDate());
                userTask.setTaskType(task.getIsDay());
                userTask.setTitle(task.getTitle());
                userTask.setTaskName(task.getNeedKey());
                if (null != task.getGetValue()){
                    userTask.setGameValue(String.valueOf(task.getGetValue()));
                }
                userTask.setCreateTime(new Date());
                userTask.setStatus("0");
                userTaskService.save(userTask);
            }
        }
        return result;
    }

    @ApiOperation(value = "登录接口")
    @PostMapping("/loginByUserName")
    public AjaxResult loginByUserName(@RequestBody LoginDto loginDto) {
        // 用户注册
        return wechatUserLoginService.loginByUserName(loginDto);
    }


    @ApiOperation(value = "音乐")
    @GetMapping("/music")
    private AjaxResult changBack() {
        String url = sysConfigService.selectConfigByKey(Constants.MUSIC_URL);
        return AjaxResult.success(url);
    }


    @ApiOperation(value = "地图")
    @GetMapping("/systemUrl")
    private AjaxResult systemUrl() {
        String url = sysConfigService.selectConfigByKey(Constants.SYSTEM_URL);
        return AjaxResult.success(url);
    }


    @ApiOperation(value = "商品列表加载")
    @GetMapping("/commityList/{type}/{pageNumebr}")
    private AjaxResult commityList(@PathVariable String type, @PathVariable Long pageNumebr) {
        AjaxResult ajaxResult = new AjaxResult();

        String param = "cateId=" + type + "&page_no=" + pageNumebr;
        String result = HttpUtils.sendGet("http://root.alltime.life/prod-api/api/yxStoreProduct", param);
        JSONObject json_test = JSONObject.parseObject(result);
        String array = json_test.getString("content");
        List<CommityVo> commityVoList = JSONObject.parseArray(array, CommityVo.class);
        return AjaxResult.success(commityVoList);
    }


    @ApiOperation(value = "QQ登录回调地址")
    @GetMapping("/qqUrl")
    private AjaxResult qqUrl() {
        AuthRequest qqAuthRequest = getQqAuthRequest();
        String authorizeUrl = qqAuthRequest.authorize(AuthStateUtils.createState());
        return AjaxResult.success(authorizeUrl);
    }


    @ApiOperation(value = "QQ登录回调")
    @GetMapping("callback/qq")
    private AjaxResult callbackQQ(AuthCallback callback, HttpServletRequest request) {
        AuthRequest qqAuthRequest = getQqAuthRequest();
        AuthResponse<AuthUser> response = qqAuthRequest.login(callback);

        if (response.ok()) {
            //实行登录信息
            String uuid = response.getData().getUuid();

        }
        return AjaxResult.success();
    }

    private AuthRequest getQqAuthRequest() {
        return new AuthQqRequest(AuthConfig.builder()
                .clientId("102087072")
                .clientSecret("Z3LRM4YoqeEbkfMo")
                .redirectUri("https://zone.alltime.life/prod-api/api/wu/account/callback/qq")
                .build());
    }


    @ApiOperation(value = "微信登录回调地址")
    @GetMapping("/webChatUrl")
    private AjaxResult webchatUrl() {
        AuthRequest authRequest = getAuthRequest();
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        return AjaxResult.success(authorizeUrl);
    }


    @ApiOperation(value = "微信授权登录")
    @GetMapping("callback/webchat")
    private void callbackWebchat(AuthCallback callback, HttpServletResponse res) throws IOException {
        AuthRequest authRequest = getAuthRequest();
        AuthResponse<AuthUser> response = authRequest.login(callback);
        System.out.println("微信response："+ response);
        StringBuilder buffer = new StringBuilder();
        buffer.append("https://zone.alltime.life/#/pages/register/login?");
        if (2000 != response.getCode()) {
            res.sendRedirect(String.valueOf(buffer));
        }
        //实行登录信息
        String uuid = response.getData().getUuid();
        QueryWrapper<TUser> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("weixin_id",uuid);
        TUser user = userService.getOne(queryWrapper);
        if (null != user){
            LoginWechatUser loginWechatUser = new LoginWechatUser();
            BeanUtils.copyProperties(user,loginWechatUser);
            // 生成token
            buffer.append("flag=1").append("&token=").append(wechatUserTokenService.createToken(loginWechatUser));
        }else {
            buffer.append("flag=0").append("&weixin_id=").append(uuid);
        }
        res.sendRedirect(String.valueOf(buffer));
    }

    private AuthRequest getAuthRequest() {
        return new AuthWeChatOpenRequest(AuthConfig.builder()
                .clientId("wx2b8c20ddc610df97")
                .clientSecret("1a6def9ce8fc6e7ba917666ae457814d")
                .redirectUri("https://zone.alltime.life/prod-api/api/wu/account/callback/webchat")
                .build());
    }

    /**
     * 小程序登录
     */
    @ApiOperation("小程序正式登录地址")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "微信小程序认证code", required = true, paramType = "query"),
    })
    @PostMapping("login/code")
    public AjaxResult getInfo(@RequestParam(name = "code", required = true) String code) {
        try {
            WxMaJscode2SessionResult session = wxMaUserService.getUserService().getSessionInfo(code);
            String openId = session.getOpenid();
            return wechatUserLoginService.login(openId);
        } catch (WxErrorException e) {
            this.logger.error(e.getMessage(), e);
            return AjaxResult.error(HttpStatus.ERROR, "系统内部异常");
        }
    }

    /**
     * 小程序登录
     */
    @ApiOperation("小程序测试登录地址")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "微信小程序认证code", required = true, paramType = "query"),
    })
    @PostMapping("login/testcode")
    public AjaxResult gettestInfo(@RequestParam(name = "code", required = true) String code) {
        try {
            //WxMaJscode2SessionResult session = wxMaUserService.getUserService().getSessionInfo(code);
            String openId = "1234456662234";
            return wechatUserLoginService.login(openId);
        } catch (Exception e) {
            this.logger.error(e.getMessage(), e);
            return AjaxResult.error(HttpStatus.ERROR, "系统内部异常");
        }
    }

    /**
     * 第三方商品对接
     */
    @ApiOperation("第三方商品对接")
    @GetMapping("thrid/commodity")
    public AjaxResult commity(CommityDto commityDto) {
        itUserService.handerThridCommity(commityDto);
        return AjaxResult.success();

    }

    /**
     * 根据参数键名查询参数值
     */
    @ApiOperation(value = "获取用户隐私协议")
    @GetMapping(value = "configKey/{configKey}")
    public AjaxResult getConfigKey(@PathVariable String configKey)
    {
        return AjaxResult.success(configService.selectConfigByKey(configKey));
    }


}
